#include "painttool.h"

CPaint2DTexture::CPaint2DTexture(){
    texture = NULL;
    img = NULL;
    width = 0;
    height = 0;
}
CPaint2DTexture::~CPaint2DTexture() {
    if (texture != NULL) {
        if(texture->isCreated())
            texture->destroy();
        delete texture;
        texture = NULL;
    }
    if (img != NULL) {
        delete img;
        img = NULL;
    }
}

void CPaint2DTexture::createImage(QString& name, QFont &font, QColor& color) {
    QFontMetrics fontMetrics(font);
    QRect bounding= fontMetrics.boundingRect(name);      //获取到字符串的外包矩形
    if (img != NULL) {
        delete img;
        img = NULL;
    }
    img = new QImage(bounding.size(),QImage::Format_ARGB32);
    img->fill(Qt::transparent);                        //使用透明色填充Image
    QPainter painter;
    painter.begin(img);
    painter.setRenderHints(QPainter::TextAntialiasing|QPainter::Antialiasing);  //开启抗锯齿
    painter.setFont(font);
    painter.setPen(color);
    painter.drawText(QRect(0,0,img->width(),img->height()),Qt::AlignCenter,name);
    painter.end();
    if (texture == NULL) {
        texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
    }
    width = img->width();
    height = img->height();
}
void CPaint2DTexture::createImage(QString& filePath) {
    img = new QImage(filePath);
    if (texture == NULL) {
        texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
    }
    width = img->width();
    height = img->height();
}
void CPaint2DTexture::resizeSize(int w, int h) {
    if (texture == NULL || img == NULL) {
        return;
    }
    int tw = img->width();
    int th = img->height();

    float ws = float(w) / float(tw);
    float hs = float(h) / float(th);

    if (ws > hs) {
        width = int(tw * hs);
        height = int(th * hs);
    }
    else{
        width = int(tw * ws);
        height = int(th * ws);
    }
}
void CPaint2DTexture::createTexture() {
    if (texture == NULL) {
        return;
    }
    if (texture->isCreated()) {
        return;
    }
    texture->create();
    texture->setData(img->mirrored());
}


//////////////////////////////////////////////
CPaint2DTextTool::CPaint2DTextTool(int n, bool occlusion){
    m_nums = n;
    textures = new CPaint2DTexture*[m_nums];
    for(int i = 0; i < m_nums; i++) {
        textures[i] = NULL;
    }
    m_occlusion = occlusion;
}
void CPaint2DTextTool::initShaderProgram()
{
    VAO.create();
    QOpenGLVertexArrayObject::Binder bind(&VAO);
    VBO.create();
    VAO.bind();
    VBO.bind();
    static float vertex[]={
        //顶点            //纹理坐标
        -1.0f,-1.0f,    0.0f,0.0f,    //左下
        -1.0f, 1.0f,    0.0f,1.0f,    //左上
        1.0f,-1.0f,    1.0f,0.0f,    //右下
        1.0f, 1.0f,    1.0f,1.0f     //右上
    };
    VBO.allocate(vertex,sizeof (vertex));
    if (m_occlusion) {
        //vec4(pos,1,1) 控制 第二个值的范围来控制深度： 0 -1 0表示最前面； 1表示最小面
        shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex,"#version 450 core\n"
                                                                    "attribute vec2 pos;\n"  //传入顶点位置
                                                                     "attribute vec2 texCoord;\n"  //颜色
                                                                     "varying vec2 outCoord;\n"  //传递给片段着色器
                                                                     "void main(void) {\n"
                                                                     "   gl_Position = vec4(pos,1,1);\n" //输出的位置
                                                                     "   outCoord = texCoord;\n"
                                                                     "}\n");
    }
    else {
        shaderProgram.addShaderFromSourceCode(QOpenGLShader::Vertex,"#version 450 core\n"
                                                                    "attribute vec2 pos;\n"
                                                                     "attribute vec2 texCoord;\n"
                                                                     "varying vec2 outCoord;\n"
                                                                     "void main(void) {\n"
                                                                     "   gl_Position = vec4(pos,0,1);\n"
                                                                     "   outCoord = texCoord;\n"
                                                                     "}\n");
    }

    shaderProgram.addShaderFromSourceCode(QOpenGLShader::Fragment,
                                          "uniform sampler2D texture;\n"
                                          "varying vec2 outCoord;\n"
                                          "void main(void) {\n"
                                          "   gl_FragColor = texture2D(texture, outCoord);\n"  //取颜色
                                          "}\n");

    shaderProgram.link();
    shaderProgram.enableAttributeArray(0);
    shaderProgram.enableAttributeArray(1);
    shaderProgram.setAttributeBuffer(0,GL_FLOAT,0,               2,4*sizeof (float));
    shaderProgram.setAttributeBuffer(1,GL_FLOAT,2*sizeof (float),2,4*sizeof (float));
    VAO.release();
    VBO.release();
}

CPaint2DTexture* CPaint2DTextTool::setText(int index, QString& name, QFont &font, QColor& color) {
    if (name == "" || index >= m_nums) {
        return NULL;
    }
    if (textures[index] == NULL) {
        textures[index] = new CPaint2DTexture();
    }
    textures[index]->createImage(name, font, color);
    return textures[index];
}

CPaint2DTexture* CPaint2DTextTool::setText(int index, QString& filePath){
    if (filePath == "" || index >= m_nums) {
        return NULL;
    }
    QFile file(filePath);
    if(file.exists()) {
        if (textures[index] == NULL) {
            textures[index] = new CPaint2DTexture();
        }
        textures[index]->createImage(filePath);
    }
    return textures[index];
}

void CPaint2DTextTool::resizeSize(int index, int w, int h){
    if (index >= m_nums) {
        return;
    }
    if (textures[index] == NULL){
        return;
    }
    textures[index]->resizeSize(w, h);
}

void CPaint2DTextTool::createTextures() {
    for(int i = 0; i < m_nums; i++) {
        if (textures[i] != NULL) {
            textures[i]->createTexture();
        }
    }
}

CPaint2DTexture* CPaint2DTextTool::getTexture(int index){
    if (index >= m_nums) {
        return NULL;
    }
    return textures[index];
}

void CPaint2DTextTool::getSize(int index, GLdouble* weight, GLdouble* height){
    if (index >= m_nums) {
        return;
    }
    CPaint2DTexture* tmp = textures[index];
    if (tmp == NULL){
        return;
    }
    *weight = tmp->width;
    *height = tmp->height;
}

bool CPaint2DTextTool::drawTexture(int index, GLdouble wx, GLdouble wy,
                 GLdouble xOffset, GLdouble yOffset){
    if (index >= m_nums) {
        return false;
    }
    CPaint2DTexture* tmp = textures[index];
    if (tmp == NULL){
        return false;
    }
    wx = wx - tmp->width * 0.5 + xOffset;
    wy = wy - tmp->height * 0.5 + yOffset;
    draw(tmp, int(wx), int(wy));
    return true;
}

bool CPaint2DTextTool::drawTexture(int index, GLdouble wx, GLdouble wy){
    if (index >= m_nums) {
        return false;
    }
    CPaint2DTexture* tmp = textures[index];
    if (tmp == NULL){
        return false;
    }
    draw(tmp, int(wx), int(wy));
    return true;
}

CPaint2DTextTool::~CPaint2DTextTool() {
    for(int i = 0; i < m_nums; i++) {
        if (textures[i] != NULL)
        {
            delete textures[i];
            textures[i] = NULL;
        }
    }
    delete textures;
}

void CPaint2DTextTool::draw(CPaint2DTexture* tmp, int wx, int wy){
    glViewport(wx, wy, tmp->width, tmp->height);
    QOpenGLVertexArrayObject::Binder bind(&VAO);
    shaderProgram.bind();
    tmp->texture->bind(0);
    glDrawArrays(GL_TRIANGLE_STRIP,0,4);
    shaderProgram.release();
}

/////////////////////////////////////////////////////////////

CPaint3DTextTool::CPaint3DTextTool(){}
CPaint3DTextTool::~CPaint3DTextTool(){}

void CPaint3DTextTool::drawText(Point3d& start, QColor& color, QString& text){
    //生成文字绘制路径
    QPainterPath path;
    path.addText(QPointF((start.x+start.y+start.z)/2, 0),  QFont("Microsoft YaHei UI", 2), text);
    //转换成多边形列表
    QList<QPolygonF> poly = path.toSubpathPolygons();
    QList<QPolygonF>::iterator iter = poly.begin();
    glLineWidth(1);
    glColor3f(color.redF(), color.greenF(), color.blueF());
    while(iter != poly.end())
    {
        glBegin(GL_LINE_LOOP);
        {
            QPolygonF::iterator it = (*iter).begin();
            while(it != iter->end())
            {
                glVertex3f(start.x+0.02, start.y - it->ry() * 0.1, start.z - it->rx() * 0.1);
                it++;
            }
        }
        glEnd();
        iter++;
    }
}

CQTTextTool::CQTTextTool(QPaintDevice *dev){
    m_painter = new QPainter(dev);
}
CQTTextTool::~CQTTextTool()
{
    if (m_painter != NULL)
    {
        delete m_painter;
        m_painter = NULL;
    }
}

void CQTTextTool::drawText(float x, float y, QString text)
{
    m_painter->setRenderHint(QPainter::TextAntialiasing); // 抗锯齿
    m_painter->drawText(x, y, text);
    m_painter->end();
}


